# -*- coding: utf-8 -*-

import socket,sys,re,os
import ui_privatechat,tcpserver,tcpclient,weather
from enum import Enum
from PyQt5.QtGui import QFont
from PyQt5.QtCore import QDataStream,QByteArray,QIODevice,QProcess,QDateTime,Qt,QTextCodec
from PyQt5.QtWidgets import QWidget,QApplication,QMessageBox,QFontDialog,QInputDialog,QColorDialog,QFileDialog
from PyQt5.QtNetwork import QUdpSocket,QHostAddress,QHostInfo


class MessageType(Enum):
    Message = 0
    NewParticipant = 1
    ParticipantLeft = 2
    FileName = 3
    Refuse = 4

class PrivateChat(ui_privatechat.Ui_Form,QWidget):
    def __init__(self):
        super(PrivateChat, self).__init__()
        self.ui = ui_privatechat.Ui_Form()
        self.ui.setupUi(self)

        self.udpSocket = QUdpSocket(self)
        self.server = tcpserver.TcpServer()
        self.port = 45454
        #按钮按钮
        self.ui.sendButton.clicked.connect(self.sendBtn_clicked)
        self.ui.quitButton.clicked.connect(self.quitBtn_clicked)
        self.ui.fontButton.clicked.connect(self.setFontBtn_clicked)
        self.ui.colorButton.clicked.connect(self.setColorBtn_clicked)
        self.ui.sendFileBtn.clicked.connect(self.sendFileBtn_clicked)
        self.ui.weatherButton.clicked.connect(self.weatherBtn_clicked)
        self.ui.catchpicBtn.clicked.connect(self.catchpicBtn_clicked)
        self.server.sendFileName.connect(self.getFileName)


    #发送数据
    def sendData(self,data):

        targetList = data.split(";")
        self.targetName = targetList[0]
        self.targetAddr = targetList[1]

        self.ui.userNameLabel.setText("{}  ip:{}".format(self.targetName,self.targetAddr))
        if not len(self.targetAddr):
            QMessageBox.warning(self,"警告","未检测到对方IP",QMessageBox.Ok)
            return
        else:
            if self.udpSocket.bind(QHostAddress(self.getIp()),self.port
                    ,QUdpSocket.ShareAddress|QUdpSocket.ReuseAddressHint) :
                self.udpSocket.readyRead.connect(self.processPendingDatagrams)

    #发送信息
    def sendMessage(self,msgType,serverAddress=''):
        messageWrite = QByteArray()  # 定义一个写的缓冲区

        out = QDataStream(messageWrite, QIODevice.WriteOnly)

        address = self.getIp()  # 获得本机IP
        localHostName = QHostInfo.localHostName()
        userName = self.getUserName()

        out.writeInt32(msgType.value)
        out.writeQString(userName)
        out.writeQString(localHostName)

        messageTime = QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss")

        if msgType == MessageType.Message:
            sendText = self.ui.messageEdit.toPlainText()  # 获得输入框的消息
            if sendText == "" :
                QMessageBox.warning(self,"警告","发送内容不能为空",QMessageBox.Ok)
                return

            out.writeQString(address)
            out.writeQString(self.getMessage())
            out.writeQString("private")


            self.ui.messageBrowser.setTextColor(Qt.blue)
            self.ui.messageBrowser.setCurrentFont(QFont("Times New Roman", 11))
            self.ui.messageBrowser.append("["+userName+"]"+messageTime)
            self.ui.messageBrowser.setAlignment(Qt.AlignRight)

            self.ui.messageBrowser.setTextColor(Qt.yellow)
            self.ui.messageBrowser.setCurrentFont(QFont("Times New Roman", 15))
            self.ui.messageBrowser.append(sendText)

            self.ui.messageBrowser.setAlignment(Qt.AlignRight)

            self.ui.messageBrowser.verticalScrollBar().setValue\
                (self.ui.messageBrowser.verticalScrollBar().maximum())

        if msgType == MessageType.NewParticipant:
            out.writeQString(address)

        if msgType == MessageType.ParticipantLeft:
            pass

        if msgType == MessageType.FileName:
            clientAddress = self.targetAddr
            out.writeQString(address)
            out.writeQString(clientAddress)
            out.writeQString(self.fileName)

        if msgType == MessageType.Refuse:
            out.writeQString(serverAddress)

        self.udpSocket.writeDatagram(messageWrite, QHostAddress(self.targetAddr), self.port)  # 广播

    # 接收发送的数据
    def processPendingDatagrams(self):
        while self.udpSocket.hasPendingDatagrams():

            messageRead = QByteArray()  #定义一个读的缓冲区
            messageRead.resize(self.udpSocket.pendingDatagramSize())
            messageBuf, ipAddress, port = self.udpSocket.readDatagram(messageRead.size())

            # 将messageBuf 转换成QByteArray格式
            messageRead = QByteArray(messageBuf)

            inStream = QDataStream(messageRead, QIODevice.ReadOnly)
            msgType = inStream.readInt32()


            messageTime = QDateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss")

            if msgType == 0:
                userName = inStream.readQString()
                localHostName = inStream.readQString()
                ipAddress = inStream.readQString()
                messageInfo = inStream.readQString()
                isPrivate = inStream.readQString()
                if self.targetAddr == ipAddress:
                    if len(isPrivate) > 0:
                        self.ui.messageBrowser.setTextColor(Qt.red)
                        self.ui.messageBrowser.setCurrentFont(QFont("Times New Roman",10))
                        self.ui.messageBrowser.append("["+userName+"]"+messageTime)
                        self.ui.messageBrowser.setAlignment(Qt.AlignLeft)

                        self.ui.messageBrowser.setCurrentFont(QFont("Times New Roman", 13))
                        self.ui.messageBrowser.append(messageInfo)
                        self.ui.messageBrowser.setAlignment(Qt.AlignLeft)
                        self.ui.messageBrowser.verticalScrollBar().setValue \
                            (self.ui.messageBrowser.verticalScrollBar().maximum())

            if msgType == 1:
                userName = inStream.readQString()
                localHostName = inStream.readQString()
                ipAddress = inStream.readQString()
                self.newParticipant(userName,localHostName,ipAddress)
            if msgType == 2:
                userName = inStream.readQString()
                localHostName = inStream.readQString()
                self.participantLeft(userName, localHostName, messageTime)

            if msgType == 3:
                userName = inStream.readQString()
                localHostName = inStream.readQString()
                ipAddress = inStream.readQString()
                clientAddress = inStream.readQString()
                fileName = inStream.readQString()
                self.hasPendingFile(userName, ipAddress, clientAddress, fileName)

            if msgType == 4:
                userName = inStream.readQString()
                localHostName = inStream.readQString()
                serverAddress = inStream.readQString()
                ipAddress = self.getIp()
                if ipAddress == serverAddress:
                    self.server.refused()

    # 新用户处理
    def newParticipant(self,userName,localHostName,ipAddress):
        self.ui.messageBrowser.setTextColor(Qt.gray)
        self.ui.messageBrowser.setCurrentFont(QFont("Roman times", 10))
        self.ui.messageBrowser.append(("{}在线！").format(userName))

    # 　用户离开处理
    def participantLeft(self, userName, localHostName, messageTime):
        self.ui.messageBrowser.setTextColor(Qt.gray)
        self.ui.messageBrowser.setCurrentFont(QFont("Roman times", 10))
        self.ui.messageBrowser.append(("{}于{}离开！").format(userName, messageTime))

    #是否接收文件
    def hasPendingFile(self,userName,serverAddress,clientAddress,fileName):
        ipAddress = self.getIp()
        if ipAddress == clientAddress :
            btn = QMessageBox.information(self,"接收文件","来自{}({})的文件：{},"
                    "是否接收？".format(userName,serverAddress
                                   ,fileName),QMessageBox.Yes,QMessageBox.No)
            if btn == QMessageBox.Yes :
                nameTuple = QFileDialog.getSaveFileName(self,"保存文件",fileName)
                name =str(nameTuple)
                if len(name) :
                    nameList = name.split(',')
                    thefilename = nameList[0].strip("('")
                    self.client = tcpclient.TcpClient()
                    self.client.setFileName(thefilename)
                    self.client.setHostAddress(QHostAddress(serverAddress))
                    self.client.show()
            else:
                self.sendMessage(MessageType.Refuse,serverAddress)

    #获取消息
    def getMessage(self):
        msg = self.ui.messageEdit.toHtml()
        self.ui.messageEdit.clear()
        self.ui.messageEdit.setFocus()

        return msg

    # 获取要发送的文件名
    def getFileName(self, name):
        self.fileName = name
        self.sendMessage(MessageType.FileName)

    #当前窗口截图截图
    def catchpicBtn_clicked(self):
        screen = QApplication.primaryScreen()
        winid = self.winId()
        pix = screen.grabWindow(int(winid))

        filename,flag = QInputDialog.getText(self,"设置截图文件名","请输入文件名")
        currentPath = os.path.abspath('.')
        root = currentPath + "/catchImg/"
        if not os.path.exists(root):
            os.mkdir(root)
        path = root+filename+".jpg"
        pix.save(path)

    # 设置颜色
    def setColorBtn_clicked(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.ui.messageEdit.setTextColor(color)

    # 设置字体
    def setFontBtn_clicked(self):
        font, ok = QFontDialog.getFont()
        if ok:
            self.ui.messageEdit.setCurrentFont(font)


    #发送消息按钮
    def sendBtn_clicked(self):
        self.sendMessage(MessageType.Message)

    #发送文件按钮
    def sendFileBtn_clicked(self):
        self.server.show()
        self.server.initServer()


    #天气信息按钮
    def weatherBtn_clicked(self):
        self.weather = weather.Weather()
        self.weather.show()


    #获取IP
    def getIp(self):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(('8.8.8.8', 80))
            ip = s.getsockname()[0]
        finally:
            pass

        return ip

    # 获取用户名
    def getUserName(self):
        envVabList = ["USER.*", "USERNAME.*", "USERDOMAIN.*", "HOSTNAME.*", "DOMAINNAME.*"]

        envrmList = QProcess.systemEnvironment()

        for envStr in envVabList:
            for envrmStr in envrmList:
                reRtn=re.search(envStr,envrmStr)
                if reRtn is None:
                    continue
                else:
                    break
            usrReRtn=reRtn.group()

            listIndex = envrmList.index(usrReRtn)
            QIODevice
            if listIndex != 1:
                stringList = envrmList[listIndex].split('=')
                if len(stringList) == 2:
                    return stringList[1]

        return "unknoen"


    # 退出按钮
    def quitBtn_clicked(self):
        self.close()

    #关闭事件
    def closeEvent(self, QCloseEvent):
        self.quitBtn_clicked()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    QTextCodec.setCodecForLocale(QTextCodec.codecForLocale())
    win = PrivateChat()
    win.show()
    sys.exit(app.exec_())







